#!/usr/bin/perl -w
# Bug reports and comments to Igor.Ermolaev@intel.com
use strict;
no warnings "portable";
use File::Spec;

use constant { FALSE=>0, TRUE=>-1 };

my @coverage         = ();
my @weights          = ();
my @reduceds         = ();
my $weight           = undef;
my @redc_weights     = ();
my $base_total       = undef;
my $base_matched     = undef;
my $base_quality     = undef;
my $base_gone_count  = 0;
my $base_gone_instrs = 0;
my $base_gone_weight = 0.0;
my $redc_total       = undef;
my $redc_matched     = undef;
my $base_coverage    = undef;
my $total_cycles     = 0;
my $total_instrs     = 0;
my $matched_instrs   = 0;
my $tavg_instrs      = undef;
my $fout_rqrd        = FALSE;
my $cnt_inputs       = 0;
my %mkl_exact_match  = ( 'mkl_blas_avx2_zgemm_zcopy_down6_ea' =>[ 'mkl_blas_avx512_zgemm_zcopy_down12_ea'  ],
                         'mkl_blas_avx2_zgemm_zcopy_right6_ea'=>[ 'mkl_blas_avx512_zgemm_zcopy_right12_ea' ],
                         'mkl_blas_avx2_zgemm_zcopy_right2_ea'=>[ 'mkl_blas_avx512_zgemm_zcopy_right4_ea'  ],
                         'mkl_blas_avx2_xsgemv_t'             =>[ 'mkl_blas_avx512_xsgemv'                 ] );
my %usr_exact_match  = ();

if( $#ARGV >= 1 && $ARGV[0] eq '-ti' )
{
   $tavg_instrs = int $ARGV[1];
   shift @ARGV;shift @ARGV;
}
if( $#ARGV >= 1 && $ARGV[0] eq '-m' )
{
   for my $rec (split /,/o,$ARGV[1])
   {
      if( $rec =~ /^(.+):(.+)$/o )
      {
         $usr_exact_match{$1} = {};
         for(split /\+/o,$2){ $usr_exact_match{$1}{$_}=TRUE;$usr_exact_match{$_}{$_}=TRUE; }
      }
   }
   shift @ARGV;shift @ARGV;
}

for( my $phase = 0; $phase <= $#ARGV; $phase++ )
{
   if( $ARGV[$phase] eq '-full' ){ $fout_rqrd = TRUE;next; }
   open CVG, $phase == 0 ? "<-" : $ARGV[$phase] or die;
   while( <CVG> )
   {
      chomp;
      if( /^\s*([[:xdigit:]]+)\s+[^\[]+\[\s*(\d+\.\d+)\%\s*\].+/o )
      {
         my $addr  = $1;
         my $share = 1.0*$2;
         my $text  = $_;
         my @line  = split /\s/o;
         my $dmng  = `c++filt -- '$line[3]'`;chomp $dmng; # remove FORTRAN's module name as well?
         if( $dmng eq $line[3] && $dmng =~ /\.[a-z]$/io )
         {
            my $isaf = substr $dmng, 0, -2;
            $dmng    = `c++filt -- '$isaf'`;chomp $dmng;
         }
         if( $dmng eq $line[3] && $dmng =~ /^(([^\.\d]+)((\.|\d+)+))+$/o )
         {
            my $ipof = substr $dmng, 0, -length $3;
            $dmng    = `c++filt -- '$ipof'`;chomp $dmng;
         }
         # normalize a bit
         $line[3] =~ s/\s//go;
         $line[3] =~ s/\(void\)/\(\)/go;
         $dmng    =~ s/\s//go;
         $dmng    =~ s/\(void\)/\(\)/go;
         if( $phase == 0 )
         {
            if( $#line >= 7 )
            {
               my $iredc = 1.0*$line[5];$iredc = 0.0004999 if $iredc == 0.0;
               if( defined $tavg_instrs )
               {
                  push @coverage, { name=>$line[3], dmng=>$dmng, module=>$line[1], addr=>$addr, share=>$share, count=>int(0.5+$tavg_instrs*(1.0*$line[5])), text=>$text, base_rqrd=>TRUE, weight=>(1.0*$line[-1]), base_count=>$tavg_instrs, base_instrs=>int($line[6])/$iredc, base_weight=>(1.0*$line[-1])/$iredc };
               }
               else
               {
                  push @coverage, { name=>$line[3], dmng=>$dmng, module=>$line[1], addr=>$addr, share=>$share, count=>int($line[4]), text=>$text, base_rqrd=>TRUE, weight=>(1.0*$line[-1]), base_count=>int($line[4])/$iredc, base_instrs=>int($line[6])/$iredc, base_weight=>(1.0*$line[-1])/$iredc };
               }
            }
            elsif( $#line > 4 && $#line != 5 )
            {
               push @coverage, { name=>$line[3], dmng=>$dmng, module=>$line[1], addr=>$addr, share=>$share, count=>int($line[4]), text=>$text, base_rqrd=>TRUE, weight=>(1.0*$line[-1]) };
            }
            else
            {
               push @coverage, { name=>$line[3], dmng=>$dmng, module=>$line[1], addr=>$addr, share=>$share, count=>int($line[4]), text=>$text, base_rqrd=>TRUE };
            }
         }
         else
         {
             if( $#line >= 10 || $#line >= 4 && $#line < 9 )
             {
                $matched_instrs+= int $line[9] if $#line >= 9;
                my @info        = ();
                my $distr_rqrd  = FALSE;
                my $accum_rqrd  = FALSE;
                if( exists $usr_exact_match{$line[3]} )
                {
                   my   $names = $usr_exact_match{$line[3]};
                   @info       = grep { exists $$names{$_->{name}} } @coverage;
                   $accum_rqrd = TRUE;
                   $distr_rqrd = TRUE if $#info > 0;
                }
                if(!@info)
                {
                   @info = grep { $_->{name} eq $line[3] && $_->{base_rqrd} == TRUE } @coverage;
                   @info = grep { $_->{dmng} eq $dmng    && $_->{base_rqrd} == TRUE } @coverage if !@info;
                }
                if(!@info)
                {
                   if( $line[3] =~ /^__svml_/io )
                   {
                      $line[3] =~ s/_\D\d$/_/io;
                      @info = grep { $_->{name} =~ /^\Q$line[3]\E\D\d$/i && $_->{base_rqrd} == TRUE } @coverage;
                      if(!@info)
                      {
                         if( $line[3] =~ /_mask_$/io )
                         {
                            $line[3] =~ s/\d+_((ha|ep)_)?mask_$//io;
                            @info = grep { $_->{name} =~ /^\Q$line[3]\E\d+_((ha|ep)_)?mask_\D\d$/i && $_->{base_rqrd} == TRUE } @coverage;
                         }
                         else
                         {
                            $line[3] =~ s/\d+_((ha|ep)_)?$//io;
                            @info = grep { $_->{name} =~ /^\Q$line[3]\E\d+_((ha|ep)_)?\D\d$/i && $_->{base_rqrd} == TRUE } @coverage;
                         }
                      }
                   }
                   elsif( $line[3] =~ /^mkl_(blas|dft)_avx\d*(_mic)?_/io )
                   {
                      if( exists $mkl_exact_match{$line[3]} )
                      {
                         for my $name (@{$mkl_exact_match{$line[3]}})
                         {
                            @info = grep { $_->{name} eq $name && $_->{base_rqrd} == TRUE } @coverage;
                            last if @info;
                         }
                      }
                      if(!@info)
                      {
                         $line[3] =~ s/^mkl_(blas|dft)_avx\d*(_mic)?_(owns|ipps|ipps_)?//io;
                         @info = grep { $_->{name} =~ /^mkl_(blas|dft)_avx\d*(_mic)?_(owns|ipps|ipps_)?\Q$line[3]\E$/i && $_->{base_rqrd} == TRUE } @coverage;
                      }
                   }
                   elsif( $line[3] =~ /^mkl_vml_/io )
                   {
                      my $sfx = $line[3];$sfx =~ s/^.*_[a-z]\d//io;
                      $line[3] =~ s/_[a-z]\d[^_]*$//io;
                      @info = grep { $_->{name} =~ /^\Q$line[3]\E_[a-z]\d\Q$sfx\E$/i && $_->{base_rqrd} == TRUE } @coverage;
                   }
                   elsif( $line[3] =~ /^[a-z]\d_/io )
                   {
                      $line[3] =~ s/^[a-z]\d_(owns|ipps(_)?)//io;
                      @info = grep { $_->{name} =~ /^[a-z]\d_(owns|ipps(_)?)\Q$line[3]\E$/i && $_->{base_rqrd} == TRUE } @coverage;
                   }
                }
                if( $distr_rqrd == TRUE && $cnt_inputs > 1 )
                {
                   # resolved later
                }
                elsif(@info) 
                {
                   my $sum_cnt = 0;
                   if( $distr_rqrd == TRUE )
                   {
                      for(@info){ $sum_cnt+= $_->{count}; }
                   }
                   $line[8] =~ s/%$//o if $#line >= 8;
                   for(@info)
                   {
                      my $w            = $sum_cnt > 0 ? (1.0*$_->{count})/$sum_cnt : 1.0;
                      $_->{base_rqrd}  = FALSE;
                      $_->{base_count} = ( exists $_->{base_count} && $accum_rqrd == TRUE ? $_->{base_count} : 0 ) + ( $w != 1.0 ? int(0.5+$w*$line[4]) : int $line[4] );
                      if( $#line >= 8 )
                      {
                         $_->{base_ctb}    = ( exists $_->{base_ctb}    && $accum_rqrd == TRUE ? $_->{base_ctb}    : 0.0 ) + $w*$line[8];
                         $_->{base_instrs} = ( exists $_->{base_instrs} && $accum_rqrd == TRUE ? $_->{base_instrs} : 0   ) + ( $w != 1.0 ? int(0.5+$w*$line[9]) : int $line[9] );
                         $_->{base_weight} = ( exists $_->{base_weight} && $accum_rqrd == TRUE ? $_->{base_weight} : 0.0 ) + $w*$line[10];
                      }
                      else
                      {
                         $_->{base_ctb}    = ( exists $_->{base_ctb}    && $accum_rqrd == TRUE ? $_->{base_ctb}    : 0.0 );
                         $_->{base_instrs} = ( exists $_->{base_instrs} && $accum_rqrd == TRUE ? $_->{base_instrs} : 0   );
                         $_->{base_weight} = ( exists $_->{base_weight} && $accum_rqrd == TRUE ? $_->{base_weight} : 0.0 );
                      }
                      last if $cnt_inputs < 2 && $distr_rqrd == FALSE; # only duplicate for multiple inputs or user specified matches
                   }
                }
                else
                {
                   $base_gone_count += int $line[4];
                   $base_gone_instrs+= int $line[9]  if $#line >= 9;
                   $base_gone_weight+= 1.0*$line[10] if $#line >= 10;
                }
             }
             elsif( $#line >= 9 ) #delete!
             {
                $matched_instrs+= int $line[9];
                $line[8] =~ s/%$//o;
                my @info = grep { $_->{name} eq $line[3] && $_->{base_rqrd} } @coverage;
                if(@info)
                {
                   for(@info)
                   {
                      $_->{base_rqrd}   = FALSE;
                      $_->{base_count}  = int $line[4];
                      $_->{base_ctb}    = 1.0*$line[8];
                      $_->{base_instrs} = int $line[9];
                      $_->{base_weight} = 0.01*$line[8];
                      last if $cnt_inputs < 2; # only duplicate for multiple inputs
                   }
                }
                else
                {
                   $base_gone_count += int $line[4];
                   $base_gone_instrs+= int $line[9];
                   $base_gone_weight+= 0.01*$line[8];
                }
             }
         }
      }
      else
      {
         push @coverage, { name=>'', dmng=>'', text=>$_ } if $phase == 0;
         if( /^\s*Total\s*:\s*(\d+)$/io )
         {
            if( $phase == 0 ){ $redc_total = int $1;$cnt_inputs++; }
            else             { $base_total = int $1; }
         }
         elsif( /^\s*Quality\s*:\s*(\d+\.\d+)%$/io )
         {
            $base_quality = 0.01*$1 if $phase != 0;
         }
         elsif( /^\s*Matched\s*:\s*(\d+)$/io )
         {
            if( $phase == 0 ){ $redc_matched = int $1; }
            else             { $base_matched = int $1; }
         }
         elsif( /^\s*pInstrs\s*:\s*(\d+)$/io )
         {
            $total_instrs = int $1 if $phase != 0;
         }
         elsif( /^\s*Reduced\s*:\s*(\d+\.\d+)%$/io )
         {
            push @reduceds, 0.01*$1 if $phase == 0;
         }
         elsif( /^\s*Weight\s*:\s*(\d+\.\d+)$/io )
         {
            if( $phase == 0 ){ push @redc_weights, 1.0*$1; }
            else             { $weight = 1.0*$1;           }
         }
         elsif( /^\s*Weights\s*:\s*.+->\s*(\d+\.\d+)%(\(\d+\.\d+%\))?\s*w\s*(.+)$/io )
         {
            if( $phase != 0 )
            {
               $base_coverage = 0.01*$1;
               @weights       = split /\s+/, $3;
            }
         }
      }
   }
   close CVG;
}
$base_matched = $base_total if !defined $base_matched;
$redc_matched = $redc_total if !defined $redc_matched;

if(@weights)
{
   my $widx      = 0;
   my $w         = 1.0*$weights[$widx];
   my @wcoverage = ();
   my %fmap      = ();
   my $data_sptd = TRUE;
   for(@coverage)
   {
      if( $_->{name} eq '' )
      {
         if( $data_sptd == TRUE )
         {
            $data_sptd = FALSE;
                 $widx++;
                    $w = $widx > $#weights ? 0.0 : 1.0*$weights[$widx];
         }
         next;
      }
      else{ $data_sptd = TRUE; }
      if( exists $fmap{$_->{module}} && exists $fmap{$_->{module}}{$_->{name}} )
      {
         my                 $fid = $fmap{$_->{module}}{$_->{name}};
         $wcoverage[$fid]{count}+= $_->{count}*$w;
         $wcoverage[$fid]{sum_w}+= $w;
         if( exists $_->{weight} )
         {
            if( exists $wcoverage[$fid]{weight} ){ $wcoverage[$fid]{weight}+= $_->{weight}; }
            else                                 { $wcoverage[$fid]{weight} = $_->{weight}; }
         }
         if( $_->{base_rqrd} == TRUE && exists $_->{base_count} )
         {
            if( exists $wcoverage[$fid]{base_count} )
            {
               $wcoverage[$fid]{base_count} += $_->{base_count} *$w;
               $wcoverage[$fid]{base_instrs}+= $_->{base_instrs}*$w;
               $wcoverage[$fid]{base_weight}+= $_->{base_weight}*$w;
            }
            else
            {
               $wcoverage[$fid]{base_count}  = $_->{base_count} *$w;
               $wcoverage[$fid]{base_instrs} = $_->{base_instrs}*$w;
               $wcoverage[$fid]{base_weight} = $_->{base_weight}*$w;
            }
         }
      }
      else
      {
         push @wcoverage, $_;
         my                         $fid = $#wcoverage;
         $fmap{$_->{module}}{$_->{name}} = $fid;
                 $wcoverage[$fid]{count} = $_->{count}*$w;
                 $wcoverage[$fid]{sum_w} = $w;
         if( $_->{base_rqrd} == TRUE && exists $_->{base_count} )
         {
            $wcoverage[$fid]{base_count}  = $_->{base_count} *$w;
            $wcoverage[$fid]{base_instrs} = $_->{base_instrs}*$w;
            $wcoverage[$fid]{base_weight} = $_->{base_weight}*$w;
         }
      }
   }
   $base_quality = 1.0;
     $redc_total = 0;
   for(@wcoverage)
   {
      if( $_->{base_rqrd} == TRUE && exists $_->{base_count} )
      {
         $_->{base_rqrd}   = FALSE;
         $_->{base_count}  = int(0.5+$_->{base_count} /$_->{sum_w});
         $_->{base_instrs} = int(0.5+$_->{base_instrs}/$_->{sum_w});
         $_->{base_weight} = int(0.5+$_->{base_weight}/$_->{sum_w});
      }
      $_->{count} = defined $tavg_instrs && exists $_->{base_count} ? int(0.5+($_->{count}/$_->{sum_w})*(1.0*$_->{base_count}/$tavg_instrs)) : int(0.5+$_->{count}/$_->{sum_w});
      $redc_total+= $_->{count};
   }
   for(@wcoverage)
   {
      $_->{share} = 100.0 * $_->{count} / $redc_total;
      $_->{text}  = "$_->{addr} $_->{module} \[".(sprintf '%0.1f%%',$_->{share})."\] $_->{name} $_->{count}";
   }
   @coverage = sort { $b->{count} <=> $a->{count} } @wcoverage;
   push @coverage, { name=>'', dmng=>'', text=>'' };
   push @coverage, { name=>'', dmng=>'', text=>"Total  : $redc_total" };
}

my $idle       = 0.0;
my $quality    = 0.0;
my $reduction  = 0.0;
my $est_instrs = 0.0;
if( $ARGV[0] eq '-summary' )
{
   for(@coverage){ $quality += $_->{weight} if exists $_->{weight}; }
}
elsif( $ARGV[0] eq '-minimum' )
{
   my %filter = ();
   for(@coverage)
   {
      next if !exists $_->{weight};
      if( !exists $filter{$_->{module}} || !exists $filter{$_->{module}}{$_->{name}} || $filter{$_->{module}}{$_->{name}} < $_->{weight} )
      {
         $filter{$_->{module}}{$_->{name}} = $_->{weight};
      }
   }
   for my $m (values %filter){ for(values %{$m}){ $quality += $_; } }
}
elsif( $ARGV[0] eq '-baseline' )
{
   my $base_seen_count  = 0;
   my $redc_seen_count  = 0;
   my $base_seen_instrs = 0;
   my $redc_unkn_count  = 0;
   for(@coverage)
   {
      if( exists $_->{base_count} && $_->{base_count} > 0 && exists $_->{base_weight} )
      {
         my $rdc = $_->{count} / $_->{base_count};
         #if( $rdc > 0.01 && $rdc < 100.0 )
         #{
            $_->{rdc}         = $rdc;
            $_->{instrs}      = int(0.5+$_->{base_instrs}*$rdc);
            $_->{weight}      = $_->{base_weight}*$rdc if !exists $_->{weight};

            $base_seen_count += $_->{base_count};
            $base_seen_instrs+= $_->{base_instrs};
            $quality         += $_->{base_weight};

            $redc_seen_count += $_->{count};
            $est_instrs      += $_->{base_instrs}*$rdc;
            $reduction       += $_->{weight};
         #}
      }
      $redc_unkn_count+= $_->{count} if exists $_->{count} && !exists $_->{rdc};
   }
   if( $base_seen_count < $base_matched )
   {
      my $rdc = $redc_unkn_count / ( $base_matched - $base_seen_count );
      my $ins = $base_seen_instrs < $matched_instrs ? ( $matched_instrs - $base_seen_instrs ) : 0;
      my $wgt = $quality          < $base_quality   ? ( $base_quality   - $quality          ) : 0.0;
      #print "$rdc $redc_unkn_count ".($base_matched-$base_seen_count)." $ins $wgt\n";

      $est_instrs+= $ins*$rdc;
      $reduction += $wgt*$rdc;

      for(@coverage)
      {
         if( !exists $_->{rdc} && exists $_->{count} )
         {
            $_->{rdc}         = $rdc;
            my         $share = $_->{count} / $redc_unkn_count;
            $_->{base_count}  = int(0.5+$_->{count}/$rdc );
            $_->{base_instrs} = int(0.5+$ins*$share);
            $_->{base_weight} = $wgt*$share;

            $_->{instrs}      = int(0.5+$ins*$rdc*$share);
            $_->{weight}      = $wgt*$rdc*$share if !exists $_->{weight};
         }
      } 
   }
   $est_instrs+= $total_instrs-$matched_instrs if $matched_instrs < $total_instrs;
   $quality    = $base_quality;
}
else
{
   my %types = ( 'unsigned int'=>'u', 'int'=>'', 'float'=>'f', 'double'=>'' );
   my $type_keys = join '|', keys %types;
   my $tck_idx = 0;
   my $ctb_idx = undef;
   my $cpi_idx = undef;
   open PRF, "<$ARGV[0]" or die;
   for( my $phase = 0; $phase < 2; $phase++ )
   {
      while( <PRF> )
      {
         chomp;
         last if $_ eq '';
         my @line = ();push @line, defined $2 ? $2 : $5 while m/(^|,)"([^"\\]*(\\.[^"\\]*)*)"|(^|,)([^,]*)/go;
         if( $line[0] =~ /^\d+(.\d+)?$/o )
         {
            my $dmng =  `c++filt -- '$line[1]'`;chomp $dmng;
               $dmng =~ s/\(($type_keys)\)([+\-\d.eE]+)/$2$types{$1}/go;
               $dmng =~ s/\s//go;
               $dmng =~ s/\(void\)/\(\)/go;
               $dmng =  'MAIN__' if $line[1] eq '_unnamed_main$_$BLK';
            $line[1] =~ s/\s//go;
            $line[1] =~ s/\(void\)/\(\)/go;
            my ( $vol, $dir, $mname ) = File::Spec->splitpath( $line[$#line-1] );
            my @info = grep { $_->{name} eq $line[1] && $_->{share} >= 0.1 } @coverage;
               @info = grep { $_->{dmng} =~ /(^|_mp_)\Q$dmng\E_?(\.|\d+)*$/i && $_->{share} >= 0.1 } @coverage if !@info;
               @info = grep { !exists $_->{cpi} } @info if $#info > 0;
            if( $#info > 0 )
            {
               my %refs = ();
               @info = grep { !$refs{$_->{module}}++ } @info; # uniq modules
            }
            @info = grep { $_->{module} =~ /^\Q$mname\E$/i } @info if $#info > 0;
            if( @info )
            {
               if( $phase == 0 )
               {
                  if( !exists $info[0]->{ctb} ) # || $info[0]->{module} =~ /^\Q$mname\E$/i )
                  {
                     $info[0]->{cpi} = 1.0*$line[$cpi_idx] if defined $cpi_idx;
                     $info[0]->{per} = 1.0*$line[$tck_idx];
                     $info[0]->{ctb} = 1.0*$line[$ctb_idx];
                  }
               }
               else
               {
                  if( !exists $info[0]->{instrs} ) # || $info[0]->{module} =~ /^\Q$mname\E$/i )
                  {
                     $info[0]->{cycles} = int $line[$tck_idx];
                     $info[0]->{instrs} = int $line[$ctb_idx];
                     $info[0]->{cpi}    = $line[$tck_idx] / $line[$ctb_idx] if !defined $cpi_idx && $line[$ctb_idx] != 0;
                  }
               }
            }
            elsif( $line[1] =~ /\<\s*unknown\(s\)\s*\>/io && ( $mname =~ /\<\s*unknown\(s\)\d+\>/io || $mname =~ /^vmlinux/io ) )
            {
               $idle += $line[3] if $phase == 0;
            }
            if( $phase == 1 )
            {
               $total_cycles += $line[$tck_idx];
               $total_instrs += $line[$ctb_idx];
            }
         }
         elsif( $#line > 0 )
         {
            my $ii = undef;
            my $ci = undef;
            for( my $i = 0; $i <= $#line; $i++ )
            {
               next if $line[$i] =~ /:PF\s*$/io;
               if( $line[$i] =~ /ratio.*cpi/io || $line[$i] =~ /CPI\s*Rate/io )
               {
                  $ci = $i if !defined $ci;
               }
               elsif( $line[$i] =~ /inst.*ret/io )
               {
                  $ii = $i if !defined $ii;
               }
            }
            $ctb_idx = $ii      if  defined $ii;
            $ctb_idx = $tck_idx if !defined $ctb_idx;
            $cpi_idx = $ci      if  defined $ci;
         }
      }
   }
   close PRF;
   for(@coverage){ $_->{weight} = $_->{ctb} / ( 100.0 - $idle ) if exists $_->{ctb}; }
   my $prv = +1e12;
   my $lst = 0;for(; $lst <= $#coverage; $lst++ )
   { 
      if( exists $coverage[$lst]{ctb} && $coverage[$lst]{ctb} >= 1.0 )
      {
         last if $coverage[$lst]{weight} > $prv;
         $prv = $coverage[$lst]{weight};
      }
      else{ last; }
   }
   $lst = 1 if $lst == 0 && $#coverage >= 0 && exists $coverage[0]{weight};
   my $wgt    = 1.0;
   my $norm   = undef;
   my $min_s2 = +1e12;
   my $max_w  = 0.0;
   for( my $i = 0; $i < $lst; $i++ )
   {
      my $s2 = 0.0;
      my $w  = 0.0;
      for(@coverage)
      {
         if( exists $_->{weight} )
         {
            my $t = $coverage[$i]{weight} * $_->{count} / $coverage[$i]{count};
            my $d = $_->{weight} - $t;
            $s2  += $d * $d;
            $w   += $t;
         }
      }
      if( $s2 < $min_s2 || $s2 == $min_s2 && $w > $max_w )
      {
         $wgt    = $coverage[$i]{weight};
         $norm   = $coverage[$i]{count};
         $min_s2 = $s2;
         $max_w  = $w;
      }
   }
   if( defined $norm ){ for(@coverage){ $_->{weight} = $wgt * $_->{count} / $norm if exists $_->{ctb}; } }
   for(@coverage){ $quality += $_->{weight} if exists $_->{weight}; }
}

if( $fout_rqrd == TRUE )
{
   for(@coverage)
   {
      if( exists $_->{rdc} )
      {
         printf "%s %.3f %d %.5f\n", $_->{text}, $_->{rdc}, $_->{instrs}, $_->{weight};
      }
      elsif( exists $_->{cpi} && exists $_->{instrs} )
      {
         printf "%s %.0f %.3f%% %s %.3f%% %s %.5f\n", $_->{text}, $_->{count} * $_->{cpi}, $_->{per}, $_->{cycles}, $_->{ctb}, $_->{instrs}, $_->{weight};
      }
      elsif( exists $_->{weight} && $_->{weight} > 0.0 )
      {
         printf "%s %.5f\n", $_->{text}, $_->{weight};
      }
      else
      {
         print "$_->{text}\n";
      }
   }
   printf "eInstrs: %.0f\n", $est_instrs if $est_instrs > 0.0;
   print "\n";
   if( @redc_weights )
   {
      my $est_coverage = 1.0;
      if( defined $base_coverage )
      {
         if( $est_instrs > 0.0 ){ $est_coverage = $est_instrs/($est_instrs+$total_instrs*(1.0/$base_coverage-1.0)); }
         else                   { $est_coverage = $base_coverage;                                                   }
      }
      @weights = @reduceds if !@weights;
      my $sum_w = 0.0;
      for(@redc_weights){ $sum_w += $_; }
      for(0..$#redc_weights){ $redc_weights[$_] /= $sum_w; }

      printf "Weights: 100.0%%->%.2f%% w", 100.0*$est_coverage;
      for(@redc_weights){ printf " %.5f", $_; }
      print "\n\n";
   }
   if( defined $weight ){ printf "Weight : %.5f\n\n", $reduction       if $reduction > 0.0; }
   else                 { printf "Reduced: %.5f%%\n", $reduction*100.0 if $reduction > 0.0; }
   printf "Quality: %.1f%%\n", $quality*100.0;
}
else
{
   printf "%.1f%%\n", $quality * 100.0;
}
exit 0;
